"""
@author: xiangping
@contact: xiangpingbu@gmail.com
@time: 2020/1/10 4:34 下午
@file: shaojie_biz_service
@Desc:
"""
import datetime
import json
import logging

import time
from typing import List

from app.database import convert
from app.exts import ironman_redis
from app.models.bo.shaojie.shaojie_bellow_location_list_bo import BellowLocationListBO
from app.models.bo.shaojie.shaojie_bellow_status_bo import SJBellowStatusBO
from app.models.bo.shaojie.shaojie_below_location_bo import BellowLocationBO
from app.models.bo.shaojie.shaojie_location_model_input_bo import LocationModelInputBO
from app.models.bo.shaojie.shaojie_status_info_bo import StatusInfoBO
from app.models.bo.shaojie.shaojie_temp_model_input_bo import TemperatureModelInputBO
from app.models.po.shaojie.shaojie_model_input_po import ShaoJieInputPO
from app.models.po.shaojie.shaojie_predict_po import ShaoJiePredictPO
from app.models.po.shaojie.shaojie_rule_po import ShaoJieRulePO
from app.services.dal.shaojie_dao_service import shaojie_predict_limited_select, predict_all_select, \
    predict_result_insert, select_simulate_input, insert_input_po, select_latest_input_at, \
    get_latest_input_cache, shaojie_history_between_query
from app.services.dal import shaojie_dao_service
from app.services.models.location_15mins_model import shaojie_loc_15m_model
from app.services.models.location_5mins_model import shaojie_loc_5m_model
from app.services.models.temperature_15mins_model import shaojie_temp_15m_model
from app.services.models.temperature_5mins_model import shaojie_temp_5m_model
from app.utils.sys_utils import copy_properties
from app.utils.constant import ShaoJieStatus
from app.controllers.Exception.iron_exception import AbnormalValueException


def get_bellow_location():
    RECORD_NUM = 180
    ORDER_FIELD = "ID"
    ORDER = "desc"

    predict_list = shaojie_predict_limited_select(limit=RECORD_NUM, order_field=ORDER_FIELD, order=ORDER)
    ave_status = get_composite_status(predict_list, 15, 5)
    composite_status = get_composite_status(predict_list, 5, 5)

    bellow_location_list_bo = BellowLocationListBO()
    size = len(predict_list)

    if size >= 1 :
        current_po: ShaoJiePredictPO = predict_list[0]
        if current_po.FQWD:
            current_locations = json.loads(current_po.FQWD.replace("\'", "\""))
            bo_list = []
            for cl in current_locations:
                bo_list.append(BellowLocationBO(**cl))
            bellow_location_list_bo.bellow_locations = bo_list
            bellow_location_list_bo.data_time = current_po.DateTime

            bellow_status_bo: SJBellowStatusBO = SJBellowStatusBO(current_po.MODEL_STATUS_15M,
                                                                  current_po.MODEL_STATUS_5M,
                                                                  current_po.DateTime)
            bellow_location_list_bo.current_bo = bellow_status_bo

    if size >= 2:
        previous_bo: ShaoJiePredictPO = predict_list[1]
        bellow_status_bo: SJBellowStatusBO = SJBellowStatusBO(previous_bo.MODEL_STATUS_15M,
                                                              previous_bo.MODEL_STATUS_5M,
                                                              previous_bo.DateTime)
        bellow_location_list_bo.previous_bo = bellow_status_bo

    bellow_location_list_bo.ave_status = ave_status
    bellow_location_list_bo.composite_estimate = composite_status

    return bellow_location_list_bo


def get_composite_status(predict_list, minute, interval):
    """
     * 获取状态评价
    :param predict_list: 模型输出结果
    :param minute:
    :param interval:
    :return: 最终评价
    """

    # 需要采集的最小值
    count = int(minute * 60 / interval)
    sorted_dict = None
    if len(predict_list) >= count:
        predict_list = predict_list[:count]
        dict = {}
        for po in predict_list:
            status = SJBellowStatusBO.get_final_status(po.MODEL_STATUS_15M, po.MODEL_STATUS_5M)
            if status in dict:
                dict[status] += 1
            else:
                dict[status] = 1

        sorted_dict = sorted(dict.items(), key=lambda x: x[1], reverse=True)

    return sorted_dict[0] if sorted_dict is not None else None


def get_status_info(continuous, latest_id, time_point='current'):
    """
    TODO： 添加只在当前时间的5分钟内后退寻找
    :param continuous:是否连续
                       不连续的话只获取最近一条数据
                       连续的话获取最近30分钟内的数据
    :param latest_id:
    :return:
    """
    count = 1
    if continuous:
        count = 30 * 60 / 5

    param = {}
    param['limit'] = count
    if latest_id is None or latest_id is '':
        param['order'] = "desc"
        param['order_field'] = "ID"
    else:
        param['latest_id'] = latest_id

    predict_list = shaojie_predict_limited_select(**param)
    status_info_list = []
    predict_list.reverse()
    if time_point == 'current':
        for po in predict_list:
            status_info_bo = StatusInfoBO(time=po.DateTime,
                                          temp=po.CURRENT_TEMP,
                                          location=po.CURRENT_LOCATION,
                                          id=po.ID)
            status_info_list.append(status_info_bo)
    elif time_point == 'future_5m':
        for po in predict_list:
            status_info_bo = StatusInfoBO(time=po.DateTime + datetime.timedelta(minutes=5),
                                          predict_temp=po.FUTURE_TEMP_5M,
                                          predict_location=po.FUTURE_LOCATION_5M,
                                          id=po.ID)
            status_info_list.append(status_info_bo)

    return status_info_list


def get_total_status_info(start_time, end_time, span):
    """

    :param start_time:
    :param end_time:
    :param span:
    :return:
    """

    sample_rate = 1
    if span <= 1:
        sample_rate = 1
    elif 1 < span <= 24:
        # 相当于分钟级别
        sample_rate = 12
    elif 24 < span <= 24 * 7:
        # 相当于15分钟级别
        sample_rate = 180
    else:
        # 相当于小时级别
        sample_rate = 720

    loc_temp_predict_list = predict_all_select(start_time=start_time,
                                               end_time=end_time,
                                               order_field="DateTime",
                                               order="asc",
                                               sample_rate=sample_rate)

    result = {
        "date": [],
        "futureDate": [],
        "temp": [],
        "location": [],
        "futureTemp": [],
        "futureLocation": []
    }

    for po in loc_temp_predict_list:
        result["date"].append(po.DateTime)
        result["futureDate"].append(po.DateTime + datetime.timedelta(minutes=5))
        result["temp"].append(po.CURRENT_TEMP)
        result["location"].append(po.CURRENT_LOCATION)
        result["futureTemp"].append(po.FUTURE_TEMP_5M)
        result["futureLocation"].append(po.FUTURE_LOCATION_5M)

    return result


def get_bellow_status_evaluation():
    """
    终结状态评价
    :return:
    """
    RECORD_NUM = 60
    ORDER_FIELD = "ID"
    ORDER = "desc"
    evaluation_dict = None
    predict_list = shaojie_predict_limited_select(limit=RECORD_NUM, order_field=ORDER_FIELD, order=ORDER)
    # 当出现烧结机机速<1时，终点预报系统抛出异常，不对终点状态进行预报。
    if len(predict_list) <= 0: return None
    if predict_list[0].CG_SJ_SJJ_SJ02_SJJXS is None: return None
    if predict_list[0].CG_SJ_SJJ_SJ02_SJJXS < 1:
        return None
    if len(predict_list) >= RECORD_NUM:
        evaluation_dict = {
            "location": get_bellow_location_status(predict_list, RECORD_NUM),
            "temp": get_bellow_temp_status(predict_list, RECORD_NUM)
        }
    return evaluation_dict if evaluation_dict is not None else None


def get_bellow_location_status(predict_list, count):
    """
    终点位置专家规则:
        预报状态小于60次时，平均状态不输出，只有当预报状态次数大于60次以后，开始进行评价状态的输出。
        统计近60次的终点状态预报结果，以最大次数的终点状态作为终点位置评价进行输出
    :return: 终点状态
    """
    sorted_dict = None
    if len(predict_list) >= count:
        predict_list = predict_list[:count]
        dict = {}
        for po in predict_list:
            status = get_location_evaluation_from_status(status_calculate(po.CURRENT_LOCATION))
            if status in dict:
                dict[status] += 1
            else:
                dict[status] = 1

        sorted_dict = sorted(dict.items(), key=lambda x: x[1], reverse=True)
    return sorted_dict[0][0] if sorted_dict is not None else None


def get_bellow_temp_status(predict_list, count):
    """
    终点温度专家规则:
        预报状态小于60次时，平均状态不输出，只有当预报状态次数大于60次以后，开始进行评价状态的输出。
        统计近60次的终点状态预报结果，以最大次数的终点状态作为终点温度评价进行输出
    :return: 终点状态
    """
    sorted_dict = None
    if len(predict_list) >= count:
        predict_list = predict_list[:count]
        dict = {}
        for po in predict_list:
            status = get_temp_evaluation_from_status(temp_status_calculate(po.CURRENT_TEMP))
            if status in dict:
                dict[status] += 1
            else:
                dict[status] = 1

        sorted_dict = sorted(dict.items(), key=lambda x: x[1], reverse=True)
    return sorted_dict[0][0] if sorted_dict is not None else None


def model_predict(simulate_time_label=None):
    loc_temp_predict_po = ShaoJiePredictPO()

    if simulate_time_label is None:
        query_time = datetime.datetime.now()
    else:
        query_time = simulate_time_label

    back_time_in_minutes = 5
    input_po = select_latest_input_at(query_time, back_time_in_minutes)
    if input_po is None:
        return None

    loc_model_input = LocationModelInputBO()
    temp_model_input = TemperatureModelInputBO()
    copy_properties(input_po, loc_model_input)
    copy_properties(input_po, temp_model_input)

    loc_5min_result = shaojie_loc_5m_model.process(loc_model_input)
    loc_15min_result = shaojie_loc_15m_model.process(loc_model_input)
    temp_5min_result = shaojie_temp_5m_model.process(temp_model_input)
    temp_15min_result = shaojie_temp_15m_model.process(temp_model_input)

    loc_temp_predict_po.FUTURE_LOCATION_5M = loc_5min_result
    loc_temp_predict_po.FUTURE_TEMP_5M = temp_5min_result
    loc_temp_predict_po.FUTURE_LOCATION_15M = loc_15min_result
    loc_temp_predict_po.FUTURE_TEMP_15M = temp_15min_result

    loc_temp_predict_po.CURRENT_LOCATION = input_po.MBTP
    loc_temp_predict_po.CURRENT_TEMP = input_po.TmaxInt

    loc_temp_predict_po.GMT_CREATE = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    loc_temp_predict_po.DateTime = input_po.DateTime

    # FQWD
    update_fqwd(loc_temp_predict_po, input_po)
    # status
    loc_temp_predict_po.MODEL_STATUS_5M = status_calculate(float(loc_5min_result))
    loc_temp_predict_po.MODEL_STATUS_15M = status_calculate(float(loc_15min_result))

    # id 自增
    loc_temp_predict_po.id = None

    predict_result_insert(loc_temp_predict_po)


def update_fqwd(loc_temp_predict_po, input_model_po):
    result = []
    tmp = {
        "index": 1,
        "temp": input_model_po.CG_SJ_SJJ_SJ02_FQWD01
    }
    result.append(tmp)

    tmp = {
        "index": 2,
        "temp": input_model_po.CG_SJ_SJJ_SJ02_FQWD02
    }
    result.append(tmp)

    tmp = {
        "index": 3,
        "temp": input_model_po.CG_SJ_SJJ_SJ02_FQWD03
    }
    result.append(tmp)

    tmp = {
        "index": 5,
        "temp": input_model_po.CG_SJ_SJJ_SJ02_FQWD05
    }
    result.append(tmp)

    tmp = {
        "index": 7,
        "temp": input_model_po.CG_SJ_SJJ_SJ02_FQWD07
    }
    result.append(tmp)

    tmp = {
        "index": 9,
        "temp": input_model_po.CG_SJ_SJJ_SJ02_FQWD09
    }
    result.append(tmp)

    tmp = {
        "index": 11,
        "temp": input_model_po.CG_SJ_SJJ_SJ02_FQWD11
    }
    result.append(tmp)

    tmp = {
        "index": 13,
        "temp": input_model_po.CG_SJ_SJJ_SJ02_FQWD13
    }
    result.append(tmp)

    tmp = {
        "index": 15,
        "temp": input_model_po.CG_SJ_SJJ_SJ02_FQWD15
    }
    result.append(tmp)

    tmp = {
        "index": 16,
        "temp": input_model_po.CG_SJ_SJJ_SJ02_FQWD16
    }
    result.append(tmp)

    tmp = {
        "index": 18,
        "temp": input_model_po.CG_SJ_SJJ_SJ02_FQWD18
    }
    result.append(tmp)

    tmp = {
        "index": 20,
        "temp": input_model_po.CG_SJ_SJJ_SJ02_FQWD20
    }
    result.append(tmp)

    tmp = {
        "index": 21,
        "temp": input_model_po.CG_SJ_SJJ_SJ02_FQWD21
    }
    result.append(tmp)

    tmp = {
        "index": 22,
        "temp": input_model_po.CG_SJ_SJJ_SJ02_FQWD22
    }
    result.append(tmp)
    loc_temp_predict_po.FQWD = json.dumps(result)


def status_calculate(loc):
    rule: ShaoJieRulePO = convert.query(ShaoJieRulePO, is_deleted=0).first()

    if loc < 0:
        raise AbnormalValueException(message="shaojie location abnormal value {}".format(loc))
    # if 0 <= loc < 58.18:
    #     return 1
    elif loc < rule.location_from:
        return 4
    elif rule.location_from <= loc <= rule.location_to:
        return 5
    elif loc > rule.location_to:
        return 6


def temp_status_calculate(temp):
    rule: ShaoJieRulePO = convert.query(ShaoJieRulePO, is_deleted=0).first()
    if temp < rule.temp_from:
        return 2
    elif rule.temp_from <= temp <= rule.temp_to:
        return 3
    else:
        return 4


def get_location_evaluation_from_status(status):
    if status in ShaoJieStatus.MODEL_STATUS_NORMAL_DICT:
        return ShaoJieStatus.MODEL_STATUS_NORMAL_DICT.get(status)
    if status in ShaoJieStatus.MODEL_STATUS_ABNORMAL_DICT:
        return ShaoJieStatus.MODEL_STATUS_ABNORMAL_DICT.get(status)


def get_temp_evaluation_from_status(status):
    if status in ShaoJieStatus.MODEL_TEMP_STATUS_NORMAL_DICT:
        return ShaoJieStatus.MODEL_TEMP_STATUS_NORMAL_DICT.get(status)
    if status in ShaoJieStatus.MODEL_TEMP_STATUS_ABNORMAL_DICT:
        return ShaoJieStatus.MODEL_TEMP_STATUS_ABNORMAL_DICT.get(status)


def simulate_data_stream(end_time, label_time=None):
    simulate_input_po = select_simulate_input(end_time)
    input_bo = ShaoJieInputPO()
    copy_properties(simulate_input_po, input_bo)
    if label_time is None:
        input_bo.DateTime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        input_bo.id = None
    else:
        input_bo.DateTime = label_time.strftime("%Y-%m-%d %H:%M:%S")
        input_bo.id = None
    input_bo.GMT_CREATE = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    insert_input_po(input_bo)


def model_predict_online():
    input_po: ShaoJieInputPO = shaojie_dao_service.get_latest_input_cache()
    BTP, MBTP, Tmax, TmaxInt = get_BTP_max(input_po)
    input_po.BTP = BTP
    input_po.MBTP = MBTP
    input_po.Tmax = Tmax
    input_po.TmaxInt = TmaxInt

    loc_model_input = LocationModelInputBO()
    temp_model_input = TemperatureModelInputBO()
    copy_properties(input_po, loc_model_input)
    copy_properties(input_po, temp_model_input)

    from app.utils.sys_utils import GaoLuEncoder

    # logging.info("model_predict_result:"+
    #              json.dumps(input_po, indent=0, separators=(',', ':'), ensure_ascii=False, cls=GaoLuEncoder))
    loc_5min_result = shaojie_loc_5m_model.process(loc_model_input)
    loc_15min_result = shaojie_loc_15m_model.process(loc_model_input)
    temp_5min_result = shaojie_temp_5m_model.process(temp_model_input)
    temp_15min_result = shaojie_temp_15m_model.process(temp_model_input)

    loc_temp_predict_po = ShaoJiePredictPO()
    copy_properties(input_po, loc_temp_predict_po)
    loc_temp_predict_po.FUTURE_LOCATION_5M = loc_5min_result
    loc_temp_predict_po.FUTURE_TEMP_5M = temp_5min_result
    loc_temp_predict_po.FUTURE_LOCATION_15M = loc_15min_result
    loc_temp_predict_po.FUTURE_TEMP_15M = temp_15min_result

    loc_temp_predict_po.CURRENT_LOCATION = input_po.MBTP
    loc_temp_predict_po.CURRENT_TEMP = input_po.TmaxInt

    loc_temp_predict_po.GMT_CREATE = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    loc_temp_predict_po.DateTime = input_po.DateTime

    # FQWD
    update_fqwd(loc_temp_predict_po, input_po)
    # status
    loc_temp_predict_po.MODEL_STATUS_5M = None if loc_5min_result is None else status_calculate(float(loc_5min_result))
    loc_temp_predict_po.MODEL_STATUS_15M = None if loc_15min_result is None else status_calculate(
        float(loc_15min_result))

    # id 自增
    loc_temp_predict_po.id = None

    shaojie_dao_service.predict_result_insert(loc_temp_predict_po)
    # shaojie_dao_service.insert_input_po(input_po)


def get_BTP_max(shaojie_input_po: ShaoJieInputPO):
    value_dict = {
        "FXFQWD16": shaojie_input_po.CG_SJ_SJJ_SJ02_FQWD16,
        "FXFQWD18": shaojie_input_po.CG_SJ_SJJ_SJ02_FQWD18,
        "FXFQWD20": shaojie_input_po.CG_SJ_SJJ_SJ02_FQWD20,
        "FXFQWD21": shaojie_input_po.CG_SJ_SJJ_SJ02_FQWD21,
        "FXFQWD22": shaojie_input_po.CG_SJ_SJJ_SJ02_FQWD22
    }

    # 如果读不到数据，直接返回一个全0， 说明供数系统异常
    for v in value_dict.values():
        if v is None:
            return [0, 0, 0, 0]
    ordered_value = sorted(value_dict.items(), key=lambda item: item[1], reverse=True)
    name, value = ordered_value[0]
    BTP = 0
    MBTP = 0
    Tmax = 0
    TmaxInt = 0

    BTP_default = 20.7
    # 当22FXFQWD为最大值时，BTP=22，MBTP=22*3.64=80.08，Tmax=22FXFQWD的数值，TmaxInt=Int（22FXFQWD）即四舍五入取整数
    if name == "FXFQWD22":
        BTP = 22
        MBTP = 80.08
        Tmax = value
        TmaxInt = int(value)

    elif name == "FXFQWD21":
        X1 = 20
        X2 = 21
        X3 = 22
        T1 = float(value_dict['FXFQWD20'])
        T2 = float(value_dict['FXFQWD21'])
        T3 = float(value_dict['FXFQWD22'])
        Y1 = T1
        Y2 = T2
        Y3 = T3
        # 采用上述3组点分别得到三个一元二次方程，计算得到方程的系数
        a = (T1 + T3 - 2 * T2) / 2
        b = (84 * T2 - 43 * T1 - 41 * T3) / 2
        c = T1 - 400 * a - 20 * b

        if a == 0:
            BTP = BTP_default
        else:
            BTP = -b / (2 * a)

        MBTP = BTP * 3.64
        Tmax = a * BTP * BTP + b * BTP + c
        TmaxInt = int(Tmax)

    elif name == "FXFQWD20":
        X1 = 18
        X2 = 20
        X3 = 21
        T1 = float(value_dict['FXFQWD18'])
        T2 = float(value_dict['FXFQWD20'])
        T3 = float(value_dict['FXFQWD21'])
        Y1 = T1
        Y2 = T2
        Y3 = T3
        # 采用上述3组点分别得到三个一元二次方程，计算得到方程的系数
        a = (T1 + 2 * T3 - 3 * T2) / 6
        b = (117 * T2 - 41 * T1 - 76 * T3) / 6
        c = T1 - 324 * a - 18 * b
        if a == 0:
            BTP = BTP_default
        else:
            BTP = -b / (2 * a)

        MBTP = BTP * 3.64
        Tmax = a * BTP * BTP + b * BTP + c
        TmaxInt = int(Tmax)

    elif name == "FXFQWD18":
        X1 = 16
        X2 = 18
        X3 = 20
        T1 = float(value_dict['FXFQWD16'])
        T2 = float(value_dict['FXFQWD18'])
        T3 = float(value_dict['FXFQWD20'])
        Y1 = T1
        Y2 = T2
        Y3 = T3
        # 采用上述3组点分别得到三个一元二次方程，计算得到方程的系数
        a = (T1 + T3 - 2 * T2) / 8
        b = (36 * T2 - 19 * T1 - 17 * T3) / 4
        c = T1 - 256 * a - 16 * b

        if a == 0:
            BTP = BTP_default
        else:
            BTP = -b / (2 * a)

        MBTP = BTP * 3.64
        Tmax = a * BTP * BTP + b * BTP + c
        TmaxInt = int(Tmax)

    elif name == "FXFQWD16":
        BTP = 16
        MBTP = 16 * 3.64
        Tmax = value
        TmaxInt = int(value)

    # 终点状态位置实时检测规则(V2新增)
    MBTP, count = MBTP_Rule(MBTP)
    after_MBTP_Rule(MBTP, count)

    return [BTP, MBTP, Tmax, TmaxInt]


def MBTP_Rule(MBTP):
    """
    终点状态位置实时检测规则

    1. 将上一个终点位置与当前终点位置做差值，当差值大于20m时，用上一时刻终点状态替换当前的终点状态并进行输出

    2. 上一时刻终点位置分布于60m～80m，当前终点位置突然小于60m时，将上一时刻终点位置作为当前终点位置进行输出，
        当连续13次（3分钟）后的终点位置仍小于60m，则输出当前的终点位置
    :param MBTP:
    :return:
    """
    # previous location
    PREVIOUS_MBTP = ironman_redis.get("PREVIOUS_MBTP")
    PREVIOUS_ABNORMAL_MBTP_COUNT = ironman_redis.get("PREVIOUS_ABNORMAL_MBTP_COUNT")
    if PREVIOUS_MBTP is None:
        PREVIOUS_MBTP = MBTP
        PREVIOUS_ABNORMAL_MBTP_COUNT = 0
    else:
        # byte to numeric
        PREVIOUS_MBTP = float(str(PREVIOUS_MBTP))
        PREVIOUS_ABNORMAL_MBTP_COUNT = int(str(PREVIOUS_ABNORMAL_MBTP_COUNT))

    if PREVIOUS_MBTP - MBTP > 20:
        return PREVIOUS_MBTP, 0
    if 60 < PREVIOUS_MBTP < 80:
        if MBTP < 60 and PREVIOUS_ABNORMAL_MBTP_COUNT < 13:
            PREVIOUS_ABNORMAL_MBTP_COUNT += 1
            return PREVIOUS_MBTP, PREVIOUS_ABNORMAL_MBTP_COUNT
        else:
            return MBTP, 0
    return MBTP, 0


def after_MBTP_Rule(MBTP, PREVIOUS_ABNORMAL_MBTP_COUNT):
    """
    缓存终点状态位置实时检测结果
    :param MBTP: 终点状态位置
    :param PREVIOUS_ABNORMAL_MBTP_COUNT: 终点状态位置连续小于60m的次数
    :return:
    """
    ironman_redis.set("PREVIOUS_MBTP", MBTP)
    ironman_redis.set("PREVIOUS_ABNORMAL_MBTP_COUNT", PREVIOUS_ABNORMAL_MBTP_COUNT)


def get_shaojie_history_between(start, end, left, right, order_by):
    return shaojie_history_between_query(start=start, end=end, left=left, right=right, order_by=order_by).all()


def get_shaojie_latest_data() -> ShaoJieInputPO:
    """
    从缓存中获取最新的烧结数据
    :return:
    """
    return None
    # return shaojie_dao_service.get_latest_input_cache()


def get_shaojie_group_data(start, end, agg_func, group_filed, group_level) -> List[dict]:
    from sqlalchemy.sql import func
    # group_level_dict = dict(minute=func.MINUTE, hour=func.HOUR, day=func.DAY)
    # agg_func_dict = dict(min=func.min, max=func.max)
    # if agg_func == 'min':
    #     _agg_func = func.min
    # _group_level = group_level_dict[group_level]
    # _agg_func = agg_func_dict[agg_func]

    return shaojie_dao_service.get_shaojie_group_data(start, end, agg_func, group_filed, group_level)
